package com.example.mfbq.arithmetic;

import android.os.Bundle;
import android.os.Message;

import com.example.mfbq.handler.ArithmeticHandler;

public class HRRNArithmetic {
    private Process[] processes;
    private ArithmeticHandler handler;
    private ProcessQueue queue = new ProcessQueue(0);

    public HRRNArithmetic(Process[] processes, ArithmeticHandler handler){
        this.processes = processes;
        this.handler = handler;
        sortProcess();
    }

    private Process continueProcess;
    private int delay;
    public void start(){
        int current = 0;
        delay = 0;
        while (true){
            Process process = hasProcess(current);
            if(process != null){
                this.queue.add(process);
                //更新界面
                Message msg = new Message();
                msg.what = 0x112;//代表要更新队列区
                msg.arg1 = 0;//代表更新第0号队列
                msg.arg2 = process.getProcessId();//代表队列区加入的内容
                msg.obj = "add";
                handler.sendMessageDelayed(msg, delay*1000);
                delay++;
            }
            Process executeProcess = null;
            if(continueProcess != null){
                executeProcess = continueProcess;
            }else{
                executeProcess = getHighPriority(current);
            }
            if(handDownProcess() == false){
                break;//所有的进程服务已经完成
            }else{
                if(executeProcess == null){//表示仍然有进程需要服务，但是当前CPU空闲
                    Message leisure = new Message();
                    leisure.what = 0x114;
                    handler.sendMessageDelayed(leisure, delay*1000);
                    delay++;

                    current++;
                    continue;
                }else{
                    Message msg = new Message();
                    msg.what = 0x111;
                    msg.arg1 = executeProcess.getProcessId();
                    msg.arg2 = current;
                    handler.sendMessageDelayed(msg, delay*1000);
                    delay++;

                    executeProcess.setDoneTime(executeProcess.getDoneTime() + 1);
                    if(executeProcess.getDoneTime() == executeProcess.getServeTime()){
                        executeProcess.setCompleteTime(current + 1);
                        continueProcess = null;

                        Message message = new Message();
                        message.what = 0x123;
                        message.arg1 = executeProcess.getProcessId();
                        message.arg2 = current + 1;
                        handler.sendMessageDelayed(message, delay*1000);
                        delay++;
                    }else{
                        continueProcess = executeProcess;
                    }
                }
            }
            current++;
        }
        sortByEnd();
        Message result = new Message();
        result.what = 0x213;
        Bundle data = new Bundle();
        data.putString("arithmetic", "hrrn");
        data.putString("result", toResultString());
        data.putDouble("art", getAverageRevolveTime());
        data.putDouble("awrt", getWAverageRevolveTime());
        result.obj = processes;
        result.setData(data);
        handler.sendMessageDelayed(result, delay*1000);
    }

    //按照进程到达时间排序
    private void sortProcess(){
        Process[] pro = this.processes;
        Process process = new Process();//用于作为交换媒介
        for(int i = 0; i < pro.length; i++){
            for(int j = 0; j < pro.length - 1 - i; j++){
                if(pro[j].getComeTime() > pro[j+1].getComeTime()){
                    process = pro[j];
                    pro[j] = pro[j+1];
                    pro[j+1] = process;
                }
            }
        }
    }
    //按进程结束时间排序
    private void sortByEnd(){
        Process[] pro = this.processes;
        Process process;
        for(int i = 0; i < pro.length; i++){
            for(int j = 0; j < pro.length - 1 - i; j++){
                if(pro[j].getCompleteTime() > pro[j+1].getCompleteTime()){
                    process = pro[j];
                    pro[j] = pro[j+1];
                    pro[j+1] = process;
                }
            }
        }
    }
    //判断数组中是否还有未完成的进程
    private boolean handDownProcess(){
        for(Process p : this.processes){
            if(p.getDoneTime() != p.getServeTime()){
                return true;
            }
        }
        return false;
    }
    //判断这一时刻是否有进程到来，有进程到来返回进程对象，无进程到来返回null
    private Process hasProcess(int currentTime){
        for(Process p : this.processes){
            if(p.getComeTime() == currentTime){
                return p;
            }
        }
        return null;
    }
    //判断当前时间点响应比最高的进程
    private Process getHighPriority(int current){
        int length = this.queue.size();
        Process pro = this.queue.poll();
        for(int i=1;i<length;i++){
            Process pro1 = this.queue.poll();
            if(pro1.getProcessPriority(current) > pro.getProcessPriority(current)){
                this.queue.add(pro);
                pro = pro1;
            }else{
                this.queue.add(pro1);
            }
        }
        if(pro != null){
            float priority = pro.getProcessPriority(current);
            Message msg = new Message();
            msg.what = 0x112;
            msg.arg1 = 0;
            msg.arg2 = pro.getProcessId();
            msg.obj = "remove";
            Bundle data = new Bundle();
            data.putString("content", "队列中"+pro.getProcessId()+"号进程响应比最高，为"+String.format("%.2f", priority));
            msg.setData(data);
            handler.sendMessageDelayed(msg, delay*1000);
            delay++;
        }
        return pro;
    }
    //得到平均周转时间
    private double getAverageRevolveTime(){
        int sum = 0;
        for(Process p : this.processes){
            sum = sum + p.getRevolveTime();
        }
        return ((double)sum) / this.processes.length;
    }
    //得到平均带权周转时间
    private double getWAverageRevolveTime(){
        double sum = 0.0;
        for(Process p : this.processes){
            sum = sum + p.getwRevolveTime();
        }
        return sum/this.processes.length;
    }
    //显示数据
    private String toResultString() {
        String str = "";
//        for(Process p : this.processes){
//            str = str + p.toString() + "\n";
//        }
        str = str + "平均周转时间为："+String.format("%.3f", getAverageRevolveTime())+"\n";
        str = str + "平均带权周转时间为："+String.format("%.3f", getWAverageRevolveTime());
        return str;
    }
}